#pragma once

#include <fstream>
#include <stdexcept>

#include "util/id-generator.h"
#include "util/stack.h"

#include "book/convert-route.h"
#include "book/index-item.h"
#include "book/article-menu.h"
#include "book/line-reader.h"


namespace book
{
class ArticleConvert
{
public:

    class StreamStateError : public std::logic_error
    {
    public:
        StreamStateError(const char *msg) : std::logic_error(msg) {}
        virtual ~StreamStateError() {}
    };

    ArticleConvert(const ConvertRoute &route, const IndexItem &item);

    void operator()();

private:
    const std::string &title() const {
        return title_;
    }

    void doConvertContent();

    bool handleSection();

    void dispatch(const std::string_view &line);

    void handleTitle(const std::string_view &line);

    void handleList(const std::string_view &line);

    void handleImg(const std::string_view &line);

    void handleCodeArea(const std::string_view &line);

    void handleReference(const std::string_view &line);

    void handleMathBlock(const std::string_view &line);

    void handleParagraph(const std::string_view &line);

    void handleText(const std::string_view &line);

    void meetTitle(int32_t level, const std::string_view &content);

    void sectionBegin();

    void sectionStop();

    class End {};

    static End end;

    static std::string e(const std::string &tag);

    static std::string e(const std::string &tag, End end);

private:
    const std::string title_;
    const ConvertRoute &route_;
    const IndexItem &item_;
    ArticleMenu menu_;
    ArticleMenu::Builder menuBuilder_;
    IdGenerator<SectionId> sectionIdGenerator_{ 1 };
    std::ifstream in_;
    LineReader reader_{ in_ };
    std::ofstream contentOut_;
    std::ofstream menuOut_;
};
} // namespace book
